package gbench.appdemo.myworld.junit;

import static gbench.appdemo.myworld.market.commodity.Commodity.*;
import static gbench.common.tree.LittleTree.IRecord.*;
import static gbench.common.tree.LittleTree.Tuple2.*;

import gbench.appdemo.myworld.market.SimpleMarket;
import gbench.appdemo.myworld.market.commodity.Commodity;
import gbench.appdemo.myworld.market.license.CommodityLicense;
import gbench.appdemo.myworld.market.license.CommodityLicenseGroup;
import gbench.common.fs.FileSystem;
import gbench.common.fs.XlsFile.SimpleExcel;
import gbench.common.tree.LittleTree;
import gbench.common.tree.LittleTree.IRecord;

import java.util.HashSet;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.*;
import org.junit.jupiter.api.Test;

/**
 * 
 * @author gbench
 *
 */
public class JunitMyWorld {

    /**
     * 
     */
    @Test
    public void foo() {

        final var machine_labor = COMMODITY("车床劳动", "天");
        final var steel_labor = COMMODITY("炼钢劳动", "天");
        final var rolling_labor = COMMODITY("轧钢劳动", "天");
        final var iron_mine = COMMODITY("煤矿", "一座");
        final var mine_labor = COMMODITY("挖矿劳动", "天");

        final var ironstone = COMMODITY("锑矿石", "吨", REC("labor", TUP2(mine_labor, 5), "mine", TUP2(iron_mine, 0)));

        final var steel = COMMODITY("钢锭", "吨", REC("labor", TUP2(steel_labor, 2), "ironstone", TUP2(ironstone, 500)));

        final var steel_panel = COMMODITY("钢板", "吨", REC("labor", TUP2(rolling_labor, 2), "steel", TUP2(steel, 500)));

        final var machine = COMMODITY("机器", "吨",
                REC("labor", TUP2(machine_labor, 2), "steel", TUP2(steel, 3), "steel_panel", TUP2(steel_panel, 3)));

        // 打印机器的原料清单
        machine.getBom().forEach(e -> {
            System.out.println(e);
        });

        System.out.println("\n需求清单");
        machine.getBomTable().forEach((k, v) -> {
            System.out.println(k + "\t" + v);
        });

        System.out.println("\ntraverse");
        machine.traverse((path, tup) -> {
            System.out.println(path + "-->" + tup);
        });
    }

    /**
     * 
     */
    @SuppressWarnings("unchecked")
    @Test
    public void qux3() {
        final var grain = COMMODITY("粮食", "公斤");
        final var rmb = COMMODITY("RMB", "元");
        final var labor = COMMODITY("产业劳动", "天");
        final var ironstone = COMMODITY("铁矿石", "吨");
        final var steel = COMMODITY("钢材", "吨");
        final var machinetool = COMMODITY("机床", "台");

        // 农业经济
        final var industry1 = SimpleMarket.of("第一产业", grain);// 创建一个市场经济

        final var miner = industry1.getCommodityLicense("矿工", labor);// 生产一个矿工
        final var iron_mine = industry1.getCommodityLicense("铁矿", ironstone);// 生产一个铁矿
        final var steel_plant = industry1.getCommodityLicense("炼钢厂", steel);
        final var machinetool_plant = industry1.getCommodityLicense("机床厂", machinetool);

        iron_mine.purchase(miner, labor, 1000000, rmb, 20000);// 铁矿厂雇佣矿工
        iron_mine.purchase(iron_mine, ironstone, 1000000, labor, 10);// 矿工挖铁矿

        steel_plant.purchase(iron_mine, ironstone, 10000000000l, rmb, 589999);// 炼钢厂买入铁矿石
        machinetool_plant.purchase(steel_plant, steel, 10000000000l, rmb, 1000000);//

        /**
         * 汇总处理
         */
        System.out.println("\n所有的交易情况:");
        final var trans = Stream.of(industry1).flatMap(mkt -> mkt.getTransactions().stream());
        final var participants = new HashSet<CommodityLicense<Commodity, Commodity>>();
        trans.forEach(e -> {
            participants.addAll(
                    L((CommodityLicense<Commodity, Commodity>) e.getPartA(), (CommodityLicense<Commodity, Commodity>) e.getPartB()));
            System.out.println(e);
        });
        participants.stream().map(e -> new CommodityLicenseGroup(e.getCode(), e)).forEach(e -> {
            System.out.println("\n" + e);
            e.trialBalance((Predicate<IRecord>) null).forEach(rec -> {
                System.out.println(rec);
            });
        });

    }

    /**
     * 对 strategy_tree 的解析：博弈树的数据处理
     */
    @Test
    public void strategy_tree() {
        final var excel = new SimpleExcel();
        final var path = "../docs/地理.xlsx";
        excel.loadXlsx(FileSystem.stream(FileSystem.path(path, this.getClass())));
        final var wbs = excel.autoDetect("wbs");// 节点结构:Id WbsCode Activity Successor Duration Resource
        excel.close();
        final var wbsItems = wbs.mapByRow(IRecord::REC).collect(Collectors.toList());
        final var wbsRoot = LittleTree.buildTree(wbsItems, // 节点集合
            wbsItems.get(wbsItems.size()-1).get("Id"),  // 根节点
            REC("id", "Id", "pid", "Successor"), // 树形结构的字段名称关系
            n->n.setLambdaName(rec->rec.getValue(r->r.str("Activity"))) // 更改名称函数:提取Activity字段作为节点名称
        );// 生成属性结构
       
        System.out.println("\n树形结构");
        LittleTree.traverse(wbsRoot, (e, i) -> {
            System.out.println("\t".repeat(i) + e.getPathCode()+"-->"+e);
        });

        System.out.println("\n叶子节点");
        wbsRoot.getAllLeaves().forEach(e -> {
            System.out.println(e);
        });

        System.out.println("\n倒序遍历");
        final Map<String, Commodity> catalog = Commodity.catalog(wbsRoot);//构建产品目录
        
        System.out.println("\n商品目录");
        catalog.forEach((k, com) -> {
            System.out.println(com);
        });

        final var rootCommodity = catalog.get(wbsRoot.getName());
        System.out.println("\n根产品原料结构");
        rootCommodity.getBom().forEach(e -> {
            System.out.println(e);
        });

        System.out.println("\n根产品核算表");
        rootCommodity.getBomTable().forEach((k, v) -> {
            System.out.println(k + "--->" + v);
        });
        
        System.out.println("\n遍历根节点的各个成分");
        rootCommodity.forEach((parents,tup)->{
            final var route = parents.stream().map(e->e._1().getName()).collect(Collectors.joining("/"));// 生成目录路径
            final var line = "\t".repeat(parents.size())+route+(route.equals("")?"":"/")+tup;
            System.out.println(line);
        });// forEach
    }//  bar

}
